import { formatTimeComponents } from '@/utils/public'
import api from '@/utils/request'

const formatTime = date => {
    const { year, month, day, hour, minute, second } = formatTimeComponents(date)
    return `${year}-${month}-${day} ${hour}:${minute}:${second}`
}

const getRecent8AM = date => {
    const recent8AM = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 8)
    return date < recent8AM ? new Date(recent8AM.setDate(recent8AM.getDate() - 1)) : recent8AM
}

const getTimeRange = (startTime, endTime) => {
    const now = new Date()
    startTime = startTime ? new Date(startTime) : getRecent8AM(now)
    endTime = endTime ? new Date(endTime) : now

    return {
        start: formatTime(startTime),
        end: formatTime(endTime)
    }
}

const getRecordData = (hours, type, startTime, endTime) => {
    const { start, end } = getTimeRange(startTime, endTime)
    if (hours) {
        return api.get(`/getRecordData?type=${type}&startTime=${start}&endTime=${end}&hours=${hours}`)
    } else {
        return api.get(`/getRecordHistoryData?type=${type}&startTime=${start}&endTime=${end}`)
    }
}

const formatLabel = key => {
    const regex = /(\d{4}-\d{2}-\d{2}) (\d{2}):\d{2}:\d{2} TO (\d{4}-\d{2}-\d{2}) (\d{2}):\d{2}:\d{2}/
    const match = key.match(regex)

    if (match) {
        const [, startDate, startHour, endDate, endHour] = match

        if (startDate === endDate) {
            return `${startDate} ${startHour}时-${endHour}时`
        } else {
            return `${startDate} ${startHour}时-次日${endHour}时`
        }
    } else {
        return key
    }
}

const getTableData = async (hours, type, startTime, endTime) => {
    let fields = [{ label: '地点', name: '' }]
    let tableData = []

    try {
        const { data } = await getRecordData(hours, type, startTime, endTime)
        tableData = data?.data || []

        if (tableData.length > 0) {
            const originalArray = Object.keys(tableData[0])
            const locationIndex = originalArray.indexOf('location')
            const locationValue = originalArray.splice(locationIndex, 1)[0]
            fields = originalArray.map(key => ({
                name: key,
                label: formatLabel(key),
                width: 100
            }))
            fields.unshift({ label: '地点', name: locationValue, width: 150 })
        }
    } catch (err) {
        console.error('Error fetching table data:', err)
    }

    return { tableData, fields }
}

const getDailyData = (from, to, type = 0) => {
    return api.get(`/getDailyRainFallAndWaterLevel?startTime=${from}&endTime=${to}&type=${type}`)
}

const getMonthlyData = (from, to, type = 0) => {
    return api.get(`/getMonthlyRainFall?startTime=${from}&endTime=${to}&type=${type}`)
}

const getYearlyData = (from, to, type = 0) => {
    return api.get(`/getYearlyRainFall?startTime=${from}&endTime=${to}&type=${type}`)
}

const calculateAverageRainfall = (records, nameToRegion) => {
    let regionRainfallTotal = {}
    let regionRainfallCount = {}

    records.forEach(record => {
        const locationName = record.location
        const rainfallKey = Object.keys(record).find(key => key.startsWith('20'))
        const rainfallValue = rainfallKey ? parseFloat(record[rainfallKey]) : 0
        const region = nameToRegion[locationName]

        if (region) {
            regionRainfallTotal[region] = (regionRainfallTotal[region] || 0) + rainfallValue
            regionRainfallCount[region] = (regionRainfallCount[region] || 0) + 1
        }
    })

    const regions = ['环市街道', '白沙街道', '棠下镇', '杜阮镇', '潮莲街道', '荷塘镇']

    return regions.map(region => {
        if (regionRainfallTotal[region] !== undefined) {
            return (regionRainfallTotal[region] / regionRainfallCount[region]).toFixed(2)
        }
        return '0.00'
    })
}

const fetchDeviceHourlyRainFallData = (from, to, device) => {
    return api.get(`/getSiteRainByHour?startTime=${from}&endTime=${to}&device=${device}`)
}

const fetchDevices = async (type = -1) => {
    return api.get(`/getLocation?type=${type}`)
}

function convertToCascadeDataFormat(data) {
    let result = {}

    data.forEach(item => {
        if (!result[item.area]) {
            result[item.area] = []
        }
        result[item.area].push({
            value: item.device,
            label: item.name
        })
    })

    return Object.keys(result).map(area => ({
        value: area,
        label: area,
        children: result[area]
    }))
}

const getDevicesWithCascadeFormat = async (type = 0) => {
    try {
        const response = await fetchDevices(type)
        const data = response.data.data
        return convertToCascadeDataFormat(data)
    } catch (error) {
        console.error('Failed to transform device data: ' + error)
        return []
    }
}

const fetchDeviceDailyRainFallData = (from, to, device) => {
    return api.get(`/getSiteRainByDays?startTime=${from}&endTime=${to}&device=${device}`)
}

const getDeviceDailyRainFallData = async (from, to, device) => {
    const axiosResponse = await fetchDeviceDailyRainFallData(from, to, device)
    const response = axiosResponse.data
    if (response.code !== 0 || !response.data) {
        throw new Error(response.msg || 'Unknown error')
    }
    const result = {}
    const fromDate = new Date(from)
    const toDate = new Date(to)

    if (response.data['field'] === 'sum2' && response.data['sum2'].length === 1) {
        result[fromDate.toISOString().slice(0, 10)] = response.data['sum2'][0].content || 0
    } else {
        response.data['sum1'].forEach(monthData => {
            const monthDate = new Date(monthData['the_month'])

            for (let day = 1; day <= 31; day++) {
                const currentDayDate = new Date(monthDate.getFullYear(), monthDate.getMonth(), day)
                if (currentDayDate >= fromDate && currentDayDate <= toDate) {
                    result[currentDayDate.toISOString().slice(0, 10)] = monthData[`d${day}`] || 0
                }
            }
        })
    }
    return result
}

const getDeviceHourlyRainFallData = async (from, to, device) => {
    const axiosResponse = await fetchDeviceHourlyRainFallData(from, to, device)
    const response = axiosResponse.data
    if (response['code'] !== 0 || !response.data) {
        throw new Error(response['msg'] || 'Unknown error')
    }
    const result = {}
    const fromDate = new Date(from)
    const toDate = new Date(to)

    if (response.data['field'] === 'sum2' && response.data['sum2'].length === 1) {
        result[fromDate.toISOString().slice(0, 10)] = response.data['sum2'][0].content || 0
    } else {
        response.data['sum1'].forEach(dayData => {
            const dayDate = new Date(dayData['the_day'])

            for (let hour = 0; hour <= 23; hour++) {
                if (dayDate >= fromDate && dayDate <= toDate) {
                    result[`${dayDate.toISOString().slice(0, 10)} ${hour}:00:00`] = dayData[`h${hour}`] || 0
                }
            }
        })
    }
    return result
}

export {
    getRecent8AM,
    getRecordData,
    getTableData,
    getDailyData,
    getMonthlyData,
    getYearlyData,
    calculateAverageRainfall,
    getDeviceHourlyRainFallData,
    getDeviceDailyRainFallData,
    getDevicesWithCascadeFormat
}
